/* $Id: OutOfSyncHandler.java,v 1.2 2010/05/27 18:51:45 nhnb Exp $ */
/***************************************************************************
 *                   (C) Copyright 2003-2010 - Marauroa                    *
 ***************************************************************************
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
package marauroa.server.game.messagehandler;

import com.agentslab.constants.APIConstants;
import games.mapacman.server.MaPacmanRPWorld;
import games.mapacman.server.ZoneDivider;
import marauroa.common.Log4J;
import marauroa.common.net.message.Message;
import marauroa.common.net.message.MessageC2SOutOfSync;
import marauroa.common.net.message.MessageS2SInSync;
import marauroa.server.game.GameServerManager;
import marauroa.server.game.SimulationStats;
import marauroa.server.game.container.ClientState;
import marauroa.server.game.container.PlayerEntry;

/**
 * When client get out of sync because it has lost part
 * of the messages stream, it can request a
 * synchronization to continue game.
 */
//TODO: Consider removing this message as with TCP it won't fail.
class InSyncHandler extends MessageHandler {

    /** the logger instance. */
    private static final marauroa.common.Logger logger = Log4J.getLogger(GameServerManager.class);
    /**
     * This message is send from client to notify that client suffered a network
     * problem and request data to be resend again to it.
     *
     * @param message
     *            the out of sync message
     */
    @Override
    public void process(Message message) {
        MessageS2SInSync msg = (MessageS2SInSync) message;
        try {
            int clientid = msg.getClientID();
            if (playerContainer.size() > APIConstants.zoneSize) {
                playerContainer.getLock().releaseLock();
                playerContainer.getLock().requestReadLock();

                long start = System.currentTimeMillis();
                int size = 0;
                for (PlayerEntry playerEntry : playerContainer) {
                    try {
//                        System.err.println("insync handler player obj:"+playerEntry.object+" clientid: "+clientid+", "+playerEntry.clientid);
                        if (playerEntry.object == null) {
                            continue;
                        }
//                        if (Integer.parseInt(playerEntry.object.get("y")) <= 40 && MaPacmanRPWorld.get().getPlayers().size() > 10 && playerEntry.object.getID().getZoneID().compareTo("start") == 0) {  //this is hardcoded at the moment but here u
                        if (playerEntry.object.get("name").compareTo("char1") == 0) //can implement strategies to divide zones
                        {
                            continue;
                        }
//                            playerEntry.state = ClientState.MIGRATE;
//                        }

                        String temp = ZoneDivider.get().getIPBasedOnPosition(playerEntry.object);
                        if (temp == null) {
                            continue;
                        }
                        if (temp.compareTo("") != 0 || temp.compareTo(APIConstants.serverHost)!=0) {
                            playerEntry.state = ClientState.MIGRATE;
                            size++;
                            ZoneDivider.get().setMigrate(true);
//                                playerContainer.getLock().releaseLock();
//                                return;
                        }


                    } catch (Exception e) {
                        System.err.println("exception in playerentry" + playerEntry + " object: " + playerEntry.object + " msgtype: " + msg.getType());
                        e.printStackTrace();
                    }
                }
                long end = System.currentTimeMillis();
                SimulationStats.getStatistics().add("migrate_computation_time", ""+(end-start));
                SimulationStats.getStatistics().add("migration_size", ""+size);
                playerContainer.getLock().releaseLock();

            }


        } catch (Exception e) {
            logger.error("error while processing S2S Sync Event", e);
        }
    }
}
